package com.colorlight.cloud.gateway.api.message.interceptor.trans.impl;

import com.colorlight.cloud.gateway.api.exception.ReflexException;
import com.colorlight.cloud.gateway.api.message.constraint.basics.object.Trans;
import com.colorlight.cloud.gateway.api.message.interceptor.trans.TransToProtoInterceptor;
import com.google.protobuf.Message;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.*;
import java.util.Objects;

/**
 *自定义类型实现 :{@link Trans} 自定义类型转化
 * @author Demon
 * @date 19/12/2023  下午3:11
 */
@Slf4j
public class ObjectTransToProtoInterceptor implements TransToProtoInterceptor {
	@Override
	public Boolean isInterceptor(Class<?> aClass) {
		return Trans.class.isAssignableFrom(aClass);
	}
	
	@Override
	public void addAttribute(Message.Builder builder, Object value, Class<?> inputClass, String methodName) {
		Trans<?,?> transObject = (Trans<?,?>)value;
		Object objectToProto = transObject.toProto();
		Method method = null;
		try {
			method = builder.getClass().getMethod(methodName, inputClass);
		} catch (NoSuchMethodException e) {
			log.error("", e);
		}
		if (method == null) {
			throw new ReflexException("获取方法失败");
		}
		// 方法调用
		try {
			method.invoke(builder, objectToProto);
		} catch (IllegalAccessException | InvocationTargetException e) {
			log.error("", e);
		}
	}
	
	@Override
	public Class<?> getInputClass(Field field) {
		return transInternalType( field.getType());
	}
	
	
	/**
	 * Trans 实现类的处理
	 * @param aClass 实现类
	 * @author Demon
	 * @date 18/12/2023/下午2:34
	 * @return 目标类型集合得内置类型 单层集合
	 */
	private Class<?> transInternalType(Class<?> aClass) {
		Type[] interfaceTypes = aClass.getGenericInterfaces();
		ParameterizedType transType = null;
		for (Type type : interfaceTypes) {
			if (type instanceof ParameterizedType &&
					((ParameterizedType) type).getRawType() == Trans.class) {
				transType = (ParameterizedType) type;
				break;
			}
		}
		try {
            //获取Trans接口的Type
			if (Objects.nonNull(transType)) {
				// 获取 Trans 接口的泛型参数 P 的 Class 对象
				return  (Class<?>) transType.getActualTypeArguments()[1];
			}
		} catch (Exception e) {
			log.error("", e);
		}
		throw new ReflexException("类型处理");
	}
}
